package com.ruoyi.wms.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.mybatis.core.page.PageQuery;
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
import com.ruoyi.wms.common.constants.EmployeesConstants;
import com.ruoyi.wms.domain.bo.employee.KMetricDetailsBo;
import com.ruoyi.wms.domain.entity.employee.EmployeeSalary;
import com.ruoyi.wms.domain.entity.employee.Employees;
import com.ruoyi.wms.domain.entity.employee.KMetricDetails;
import com.ruoyi.wms.domain.entity.employee.KSalarySetup;
import com.ruoyi.wms.domain.vo.KMetricDetailsVo;
import com.ruoyi.wms.mapper.EmployeeSalaryMapper;
import com.ruoyi.wms.mapper.EmployeesMapper;
import com.ruoyi.wms.mapper.KMetricDetailsMapper;
import com.ruoyi.wms.mapper.KSalarySetupMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * K项指标明细Service业务层处理
 *
 * @author 邓滔滔
 * @date 2024-11-27
 */
@RequiredArgsConstructor
@Service
public class KMetricDetailsService {

    private final KMetricDetailsMapper kMetricDetailsMapper;

    private final KSalarySetupMapper kSalarySetupMapper;

    private final EmployeeSalaryMapper employeeSalaryMapper;

    private final EmployeesMapper employeesMapper;

    /**
     * 查询K项指标明细
     */
    public KMetricDetailsVo queryById(Long id) {
        return kMetricDetailsMapper.selectVoById(id);
    }

    /**
     * 查询K项指标明细列表
     */
    public TableDataInfo<KMetricDetailsVo> queryPageList(KMetricDetailsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<KMetricDetails> lqw = buildQueryWrapper(bo);
        Page<KMetricDetailsVo> result = kMetricDetailsMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询K项指标明细列表
     */
    public List<KMetricDetailsVo> queryList(KMetricDetailsBo bo) {
        LambdaQueryWrapper<KMetricDetails> lqw = buildQueryWrapper(bo);
        return kMetricDetailsMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<KMetricDetails> buildQueryWrapper(KMetricDetailsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<KMetricDetails> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getStoreId() != null, KMetricDetails::getStoreId, bo.getStoreId());
        lqw.between(params.get("beginCalculationPeriod") != null && params.get("endCalculationPeriod") != null,
            KMetricDetails::getCalculationPeriod, params.get("beginCalculationPeriod"), params.get("endCalculationPeriod"));
        lqw.eq(bo.getActualAmount() != null, KMetricDetails::getActualAmount, bo.getActualAmount());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            KMetricDetails::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
        return lqw;
    }

    /**
     * 新增K项指标明细
     */
    public void insertByBo(KMetricDetailsBo bo) {
        BigDecimal totalAmount = getTotalAmount(bo);
        bo.setActualAmount(totalAmount);
        bo.setKTotalSalay(totalAmount.add(EmployeesConstants.K_BASE_SALAY));
        KMetricDetails add = MapstructUtils.convert(bo, KMetricDetails.class);
        kMetricDetailsMapper.insert(add);
        setEmployeeKSalay(bo.getStoreId(), bo.getCalculationPeriod(), bo.getKTotalSalay());

    }

    /**
     * 计算总金额
     *
     * @param bo
     * @return
     */
    private BigDecimal getTotalAmount(KMetricDetailsBo bo) {
        //按照指标计算该月的总金额
        //营业额
        BigDecimal revenue = bo.getRevenue();
        //小吃销售
        BigDecimal snackSales = bo.getSnackSales();
        //新增会员数
        Long newMembers = bo.getNewMembers();
        //饱和数
        Long saturation = bo.getSaturation();
        List<KSalarySetup> setups = kSalarySetupMapper.selectList();
        KSalarySetup k1 = setups.get(0);
        KSalarySetup k2 = setups.get(1);
        KSalarySetup k3 = setups.get(2);
        KSalarySetup k4 = setups.get(3);
        //计算金额函数
        BigDecimal kSalary = calculateAmount(revenue, k1);
        BigDecimal kSnackSales = calculateAmount(snackSales, k2);
        BigDecimal kNewMembers = calculateAmount(new BigDecimal(newMembers), k3);
        BigDecimal kSaturation = calculateAmount(new BigDecimal(saturation), k4);
        //总金额
        return kSalary.add(kSnackSales).add(kNewMembers).add(kSaturation);
    }

    /**
     * 计算某项指标的金额
     *
     * @param number      - 金额
     * @param salarySetup - 指标设置
     * @return
     */
    private BigDecimal calculateAmount(BigDecimal number, KSalarySetup salarySetup) {
        BigDecimal balancePoint = salarySetup.getBalancePoint();
        BigDecimal weight = salarySetup.getWeight();
        //营业额大于平衡点
        if (number.compareTo(balancePoint) > 0) {
            //((营业额-平衡点)/奖励刻度*奖励金额)*权重
            BigDecimal rewardScale = salarySetup.getRewardScale();
            BigDecimal reward = salarySetup.getReward();
            //(营业额-平衡点)/奖励刻度
            BigDecimal rewardAmount = (number.subtract(balancePoint)).divide(rewardScale, 2, RoundingMode.HALF_UP);
            //奖励金额*权重
            return rewardAmount.multiply(reward).multiply(weight);
        } else {
            //((平衡点-营业额)/处罚刻度*处罚金额)*权重
            BigDecimal punishmentScale = salarySetup.getPunishmentScale();
            BigDecimal punishment = salarySetup.getPunishment();
            //(平衡点-营业额)/处罚刻度
            BigDecimal punishmentAmount = (balancePoint.subtract(number)).divide(punishmentScale, 2, RoundingMode.HALF_UP);
            //处罚金额*权重
            //返回负的
            return punishmentAmount.multiply(punishment).multiply(weight).multiply(new BigDecimal(-1));
        }
    }

    /**
     * 修改K项指标明细
     */
    public void updateByBo(KMetricDetailsBo bo) {
        BigDecimal totalAmount = getTotalAmount(bo);
        bo.setActualAmount(totalAmount);
        bo.setKTotalSalay(totalAmount.add(EmployeesConstants.K_BASE_SALAY));
        KMetricDetails update = MapstructUtils.convert(bo, KMetricDetails.class);
        kMetricDetailsMapper.updateById(update);
        //设置员工k薪酬
        setEmployeeKSalay(bo.getStoreId(), bo.getCalculationPeriod(), bo.getKTotalSalay());
    }

    /**
     * 批量删除K项指标明细
     */
    public void deleteByIds(Collection<Long> ids) {
        kMetricDetailsMapper.deleteBatchIds(ids);
    }

    /**
     * 设置员工k薪酬
     */
    public void setEmployeeKSalay(Long storeId, Date period, BigDecimal kTotalSalay) {
        //获取月初月末
        DateTime begin = DateUtil.beginOfMonth(period);
        DateTime end = DateUtil.endOfMonth(period);
        List<Employees> employees = employeesMapper.selectList(Wrappers.<Employees>lambdaQuery()
            .eq(Employees::getStoreId, storeId));

        for (Employees employee : employees) {
            EmployeeSalary employeeSalary = employeeSalaryMapper.selectOne(Wrappers.<EmployeeSalary>lambdaQuery()
                .eq(EmployeeSalary::getEmployeeId, employee.getId())
                .between(EmployeeSalary::getPayPeriod, begin, end));
            if (employeeSalary != null) {
                employeeSalary.setBaseSalary(kTotalSalay);
            }
            employeeSalaryMapper.updateById(employeeSalary);
        }
    }
}
